﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Common;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using NutriStat;
using NutriStat.Data;

namespace NutriStat
{
    public partial class OpenTableDialogBase : NutriDialog
    {
        #region Data
        #region Protected Data
        protected FormBase menu;
        protected IDbDriver db;
        protected DataTable dt;
        #endregion Protected Data

        #region Private Data
        private string connectionString;
        private string fileName;
        private bool allowFileCreation;
        #endregion Private Data
        
        #region Internal Data
        #endregion Internal Data
        #endregion Data

        #region Constructors
        /// <summary>
        /// Constructor
        /// </summary>
        public OpenTableDialogBase() : base()
        {
            InitializeComponent();
            AllowFileCreation = false;
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="callingMenu">The form that opened this form</param>
        public OpenTableDialogBase(FormBase callingMenu) : base()
        {
            InitializeComponent();            
            menu = callingMenu;
            menu.UseWaitCursor = true;
            menu.Enabled = false;

            ConnectionString = string.Empty;
            AllowFileCreation = false;

            db = new AccessDatabase();
            dt = new DataTable();
        }

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="callingMenu">The form that opened this form</param>
        /// <param name="database">The database to load</param>
        /// <param name="table">The table in the database</param>
        public OpenTableDialogBase(FormBase callingMenu, NutriStat.Data.IDbDriver database, DataTable table)
            : base()
        {
            InitializeComponent();
            menu = callingMenu;
            menu.UseWaitCursor = true;
            menu.Enabled = false;

            ConnectionString = menu.GuiMediator().ConnectionString;
            maskedTextBoxDataSource.Text = ConnectionString;
            AllowFileCreation = false;

            db = database;
            dt = table;

            PopulateTableNames();
        }

        ~OpenTableDialogBase()
        {
            menu.UseWaitCursor = false;
            menu.Enabled = true;
            db.Dispose();
            dt.Dispose();
        }
        #endregion Constructors

        #region Events
        /// <summary>
        /// Handles the Load event for the form
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void OpenTableDialogBase_Load(object sender, EventArgs e)
        {
            ConfigureFormControls();
        }

        /// <summary>
        /// Handles the Click event for the cancel button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void buttonCancel_Click(object sender, EventArgs e)
        {
            menu.UseWaitCursor = false;
            menu.Enabled = true;
            db.Dispose();
            dt.Dispose();
            this.Close();
        }

        /// <summary>
        /// Handles the Click event for the data source browse button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void buttonDataSourceBrowse_Click(object sender, EventArgs e)
        {
            // If the user selected Access
            if (comboBoxDatabaseType.Text.Equals("Microsoft Access Database"))
            {
                listBoxTables.Items.Clear();

                DialogResult result = openFileDialogExistingTable.ShowDialog();

                if (result == DialogResult.Cancel)
                {
                    return;
                }

                FileName = openFileDialogExistingTable.FileName;
                if (FileName.Equals(string.Empty))
                {
                    return;
                }                

                if (AllowFileCreation)
                {                 
                    if (!CheckFileExists(FileName))
                    {
                        // Show a dialog box and prompt the user if they want to create the file.
                        result = MessageBox.Show(this, SharedStrings.FILE_DOES_NOT_EXIST +
                            SharedStrings.DO_YOU_WANT_TO_CREATE, SharedStrings.CREATE_FILE, 
                            MessageBoxButtons.YesNo, MessageBoxIcon.Question);

                        if (result == DialogResult.Yes)
                        {                            
                            // Create our stream reader objects.
                            Stream stream = null;
                            FileStream fileStream = null;

                            // Try creating the file.
                            try
                            {
                                // Create our byte array
                                byte[] bArray;
                                System.Reflection.Assembly objAssembly = System.Reflection.Assembly.GetExecutingAssembly();

                                // Get the NutriBlank2007.accdb file, which is currently an embedded resource
                                // within the solution
                                if (FileName.EndsWith(".accdb"))
                                {
                                    stream = objAssembly.GetManifestResourceStream("NutriStat.Resources.NutriBlank2007.accdb");
                                }
                                else if (FileName.EndsWith(".mdb"))
                                {
                                    stream = objAssembly.GetManifestResourceStream("NutriStat.Resources.NutriBlank2003.mdb");
                                }
                                // Make our array the size of the stream, which is now getting our blank Access database
                                bArray = new Byte[stream.Length];
                                stream.Read(bArray, 0, (int)stream.Length);
                                // Create the new file
                                fileStream = new FileStream(FileName, System.IO.FileMode.Create);
                                // Write the file out
                                fileStream.Write(bArray, 0, (int)stream.Length);
                                // Close the stream
                                fileStream.Close();
                            }
                            catch (Exception ex)
                            {
                                //throw;
                                MessageBox.Show(ex.Message);
                            }
                            finally
                            {
                                // Cleanup...
                                //fileStream.Close();
                                fileStream = null;
                                stream = null;
                            }
                        }
                        // If they say no...
                        else
                        {
                            // Do nothing. They don't want to create the file, so
                            // we obviously want to skip trying to connect to it!
                            return;
                        }
                    }                
                }

                db = new AccessDatabase();
                db.ConnectionString = AccessDatabase.BuildConnectionString(FileName, null);

                menu.GuiMediator().ConnectionString = FileName;
                maskedTextBoxDataSource.Text = FileName;                
                PopulateTableNames();
            }

            // If the user selected SQL Server
            else if (comboBoxDatabaseType.Text.Equals("Microsoft SQL Server Database"))
            {
                // Show our SQL connection dialog
                SQLConnectDialog connectSQL = new SQLConnectDialog(this);
                connectSQL.Show();
            }
            // This must be re-set to the program's default, otherwise the program will be looking
            // for the reference MDBs inside the directory in which the file was just opened.
            Directory.SetCurrentDirectory(NutriConfig.GetCurrentDirectory());
        }

        /// <summary>
        /// Handles the Click event for the clear button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void buttonClear_Click(object sender, EventArgs e)
        {
            maskedTextBoxDataSource.Text = string.Empty;
            listBoxTables.Items.Clear();
            textBoxTableName.Clear();
        }

        /// <summary>
        /// Handles the Click event for the OK button
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void buttonOK_Click(object sender, EventArgs e)
        {
            if (listBoxTables.SelectedItem == null)
                return;

            try
            {

                DataTable temp = db.GetTableData(listBoxTables.SelectedItem.ToString(), "*");
                if (temp.Columns.Contains("fldIdNo") && temp.Columns.Contains("fldCurrentDate"))
                {
                    dt = db.GetTableData(listBoxTables.SelectedItem.ToString(), "*", "fldIdNo, fldCurrentDate ASC");
                }
                else
                {
                    dt = db.GetTableData(listBoxTables.SelectedItem.ToString(), "*");
                }
            

                dt.TableName = listBoxTables.SelectedItem.ToString();

                menu.GuiMediator().Database = db;
                menu.GuiMediator().Table = dt;
                menu.OpenDatabase();

                this.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Handles the FormClosed event for the form
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void OpenTableDialogBase_FormClosed(object sender, FormClosedEventArgs e)
        {
            menu.UseWaitCursor = false;
            menu.Enabled = true;
            // This must be re-set to the program's default, otherwise the program will be looking
            // for the reference MDBs inside the directory in which the file was just opened.
            Directory.SetCurrentDirectory(NutriConfig.GetCurrentDirectory());
        }

        /// <summary>
        /// Handles the KeyPress event for the table name text box
        /// </summary>
        /// <param name="sender">Object that fired the event</param>
        /// <param name="e">.NET supplied event parameters</param>
        protected virtual void textBoxTableName_KeyPress(object sender, KeyPressEventArgs e)
        {
            base.OnKeyPress(e);

            string keyInput = e.KeyChar.ToString();

            if (Char.IsLetterOrDigit(e.KeyChar) || Char.IsControl(e.KeyChar))
            {
                // Digits and letters are okay
            }
            else
            {
                // Consume this invalid key
                e.Handled = true;
            }
        }
        #endregion Events

        #region Properties
        #region Public Properties
        /// <summary>
        /// Gets/sets the file name being used; only applicable for MS Access        
        /// </summary>
        public string FileName
        {
            get
            {
                return fileName;
            }
            set
            {
                fileName = value;
            }
        }

        /// <summary>
        /// Gets/sets the connection string 
        /// </summary>
        public string ConnectionString
        {
            get
            {
                return connectionString;
            }
            set
            {
                connectionString = value;
            }
        }

        /// <summary>
        /// Gets/sets whether this dialog can create a new file
        /// </summary>
        public bool AllowFileCreation
        {
            get
            {
                return allowFileCreation;
            }
            set
            {
                allowFileCreation = value;
            }
        }

        
        #endregion Public Properties

        #region Protected Properties
        #endregion Protected Properties

        #region Private Properties
        #endregion Private Properties
        #endregion

        #region Methods
        #region Public Methods
        #endregion Public Methods

        #region Protected Methods
        /// <summary>
        /// Checks if the given file name exists.
        /// </summary>
        /// <param name="value">Sets whether or not to check for the existence of the file.</param>
        protected void SetCheckFileExists(bool value)
        {
            openFileDialogExistingTable.CheckFileExists = value;
        }

        /// <summary>
        /// Gets whether or not to check for the existence of a file.
        /// </summary>
        /// <returns>bool</returns>
        protected bool GetCheckFileExists()
        {
            return openFileDialogExistingTable.CheckFileExists;
        }

        /// <summary>
        /// Begins the process for populating the list of table names when using a SQL Server database.
        /// </summary>        
        protected internal void PopulateSQL()
        {
            db = new SqlDatabase();
            db.ConnectionString = ConnectionString;
            menu.GuiMediator().ConnectionString = ConnectionString;
            maskedTextBoxDataSource.Text = ConnectionString;
            PopulateTableNames();
        }

        /// <summary>
        /// Begins the process for populating the list of table names when using a MySQL database.
        /// </summary>        
        /// <param name="server">The server from which to pull the database.</param>
        /// <param name="database">The database to open.</param>        
        /// <param name="username">The username to use.</param>
        /// <param name="password">The password.</param>       
        protected internal void PopulateMySQL(string server, string database, string username, string password)
        {
            //db = new MySqlDatabase();
            //db.ConnectionString = ConnectionString;
            //menu.Patient.ConnectionString = ConnectionString;
            //maskedTextBoxDataSource.Text = ConnectionString;
            //PopulateTableNames();
        }

        /// <summary>
        /// Configures the form controls based on the user's preferences and regional settings.
        /// </summary>
        protected internal override void ConfigureFormControls()
        {
            //statusStripMainMenu.Visible = false;
            this.Text = SharedStrings.OPEN_TABLE;
            labelDatabaseType.Text = SharedStrings.DATABASE_TYPE;
            labelDataSource.Text = SharedStrings.DATA_SOURCE;
            groupBoxDataSourceExplorer.Text = SharedStrings.DATA_SOURCE_EXPLORER;
            buttonCancel.Text = SharedStrings.CANCEL;
            buttonOK.Text = SharedStrings.OK;
            buttonClear.Text = SharedStrings.CLEAR;
            buttonHelp.Text = SharedStrings.HELP;
            labelTableName.Text = SharedStrings.NEW_TABLE_NAME;
        }

        /// <summary>
        /// Populates the form's listBox with all the table names in the current database.
        /// </summary>
        protected void PopulateTableNames()
        {
            maskedTextBoxDataSource.Text = menu.GuiMediator().ConnectionString;

            List<string> tableNames = db.GetTableNames();
            listBoxTables.Items.Clear();

            foreach (string name in tableNames)
            {
                listBoxTables.Items.Add(name);
            }
        }

        /// <summary>
        /// Clears the list of table names
        /// </summary>        
        protected internal void ClearList()
        {
            listBoxTables.Items.Clear();
        }

        /// <summary>
        /// Creates a blank table inside the currently-selected database.
        /// </summary>
        /// <param name="tableName">The name of the table to be created.</param>
        /// <returns>bool</returns>
        protected bool CreateTable(string tableName)
        {
            return NutriDatabase.CreateNutriTable(tableName, db);
        }
        #endregion Protected Methods

        #region Private Methods
        /// <summary>
        /// Checks whether a file exists
        /// </summary> 
        /// <param name="fileName">The file to check</param>
        /// <returns>bool</returns>
        private bool CheckFileExists(string fileName)
        {
            return System.IO.File.Exists(fileName);
        }
        #endregion Private Methods
        #endregion Methods

    } // end class

} // end namespace
